package com.oritsh.dicom.scu;

import com.oritsh.dicom.constant.CGetInformatiionModel;
import com.oritsh.dicom.constant.CMoveInformationModel;
import com.oritsh.dicom.exception.GetException;
import org.dcm4che.data.Attributes;
import org.dcm4che.data.Tag;
import org.dcm4che.data.UID;
import org.dcm4che.data.VR;
import org.dcm4che.net.*;
import org.dcm4che.net.pdu.AAssociateRQ;
import org.dcm4che.net.pdu.PresentationContext;
import org.dcm4che.net.pdu.RoleSelection;
import org.dcm4che.net.service.DicomServiceRegistry;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by xiashenpin on 16/1/31.
 */
public class MoveSCU extends  DicomSCU {

    Attributes keys = new Attributes();

    CMoveInformationModel model ;

    protected int priority;

    private int cancelAfter;

    private String destination;

    List<String> tsuids = new ArrayList<>();

    public MoveSCU(CMoveInformationModel model, String aeCalling) {
        super(aeCalling);
        this.model = model;


       // tsuids.add(UID.JPEGLossless);
        //tsuids.add(UID.JPEGLSLossless);
        tsuids.addAll(Arrays.asList(IVR_LE_FIRST));
        addLevel(null);
    }

    public MoveSCU( String aeCalling){
        this(CMoveInformationModel.StudyRoot,aeCalling);
    }

    private void addLevel(String s) {
        if (s == null)
            s = this.model.level;
        keys.setString(Tag.QueryRetrieveLevel, VR.CS, s);
    }

    @Override
    protected PresentationContext createPresentationContext() {
        return new PresentationContext(1, model.cuid, tsuids.toArray(new String[0]));
    }

    @Override
    protected AAssociateRQ createAAssociateRQ(ApplicationEntity aeCalling, ApplicationEntity aeCalled) {

        String [] tsuids = this.tsuids.toArray(new String[0]);
        AAssociateRQ rq = super.createAAssociateRQ(aeCalling, aeCalled);
        addOfferedStorageSOPClass(rq, UID.ComputedRadiographyImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.DigitalXRayImageStorageForPresentation,tsuids);
        addOfferedStorageSOPClass(rq, UID.DigitalXRayImageStorageForProcessing,tsuids);
        addOfferedStorageSOPClass(rq, UID.DigitalMammographyXRayImageStorageForPresentation,tsuids);
        addOfferedStorageSOPClass(rq, UID.DigitalMammographyXRayImageStorageForProcessing,tsuids);
        addOfferedStorageSOPClass(rq, UID.CTImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.UltrasoundMultiFrameImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.MRImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.UltrasoundImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.SecondaryCaptureImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.GrayscaleSoftcopyPresentationStateStorageSOPClass,tsuids);
        addOfferedStorageSOPClass(rq, UID.XRayAngiographicImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.XRayRadiofluoroscopicImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.NuclearMedicineImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.VLPhotographicImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.VideoPhotographicImageStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.BasicTextSRStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.EnhancedSRStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.KeyObjectSelectionDocumentStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.XRayRadiationDoseSRStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.EncapsulatedPDFStorage,tsuids);
        addOfferedStorageSOPClass(rq, UID.PositronEmissionTomographyImageStorage,tsuids);

        return rq;
    }

    @Override
    protected Device createDevice(Connection localConn, ApplicationEntity local) {
        Device device = super.createDevice(localConn, local);
        device.setDimseRQHandler(createServiceRegistry());
        return device;
    }

    private DicomServiceRegistry createServiceRegistry() {
        DicomServiceRegistry serviceRegistry = new DicomServiceRegistry();
        //serviceRegistry.addDicomService(storageSCP);
        return serviceRegistry;
    }

    private AAssociateRQ addOfferedStorageSOPClass(AAssociateRQ rq, String cuid,String ... tsuid) {

        if (!rq.containsPresentationContextFor(cuid))
            rq.addRoleSelection(new RoleSelection(cuid, false, true));

        for (String ts : tsuids)
            rq.addPresentationContext(new PresentationContext(
                    2 * rq.getNumberOfPresentationContexts() + 1, cuid, ts));
        return rq;
    }

    public void retrieve(Attributes keys, DimseRSPHandler handler) throws IOException, InterruptedException {
        as.cmove(model.cuid, priority, keys, null, getDestination(), handler);
    }

    public DimseRSP retrieve(Attributes attributes) throws Exception {
        FutureDimseRSP rsp = new FutureDimseRSP(as.nextMessageID());
        rsp.setAutoCancel(cancelAfter);
        retrieve(attributes, rsp);
        return rsp;
    }

    public String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        this.destination = destination;
    }
}
